{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Microblaze Python Libraries\n",
    "\n",
    "In addition to using the `pynqmb` libraries from C it is also possible to create Python wrappers for the libraries directly. PYNQ provides the `MicroblazeLibrary` class for this purpose.\n",
    "\n",
    "The `MicroblazeLibrary` class takes a list of libraries as a construction parameter which should be the names of the header files desired without the `.h` file extension. All of the constants and functions will then become members of the instance of the class.\n",
    "\n",
    "For this example we are going to interact with the Grove ADC device attached to a Pmod-Grove Adapter. We are going to want the `i2c` library for interacting with the device and the `pmod_grove` library to find the pins we want to connect to."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq.overlays.base import BaseOverlay\n",
    "from pynq.lib import MicroblazeLibrary\n",
    "\n",
    "base = BaseOverlay('base.bit')\n",
    "lib = MicroblazeLibrary(base.PMODA, ['i2c', 'pmod_grove'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now inspect the lib to see all of the functions we can call and constants we have access."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['PMOD_G1_A',\n",
       " 'PMOD_G1_B',\n",
       " 'PMOD_G2_A',\n",
       " 'PMOD_G2_B',\n",
       " 'PMOD_G3_A',\n",
       " 'PMOD_G3_B',\n",
       " 'PMOD_G4_A',\n",
       " 'PMOD_G4_B',\n",
       " '__class__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__getattribute__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__module__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " '__weakref__',\n",
       " '_build_constants',\n",
       " '_build_functions',\n",
       " '_mb',\n",
       " '_populate_typedefs',\n",
       " '_rpc_stream',\n",
       " 'active_functions',\n",
       " 'i2c_close',\n",
       " 'i2c_get_num_devices',\n",
       " 'i2c_open',\n",
       " 'i2c_open_device',\n",
       " 'i2c_read',\n",
       " 'i2c_write',\n",
       " 'release',\n",
       " 'reset',\n",
       " 'visitor']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(lib)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we need to open our I2C device using the `i2c_open` function. This will return us an `i2c` object we can use for interacting with the bus."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "device = lib.i2c_open(lib.PMOD_G4_B, lib.PMOD_G4_A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can check the functions we can call by using `dir` again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['__class__',\n",
       " '__delattr__',\n",
       " '__dict__',\n",
       " '__dir__',\n",
       " '__doc__',\n",
       " '__eq__',\n",
       " '__format__',\n",
       " '__ge__',\n",
       " '__getattribute__',\n",
       " '__gt__',\n",
       " '__hash__',\n",
       " '__index__',\n",
       " '__init__',\n",
       " '__init_subclass__',\n",
       " '__int__',\n",
       " '__le__',\n",
       " '__lt__',\n",
       " '__module__',\n",
       " '__ne__',\n",
       " '__new__',\n",
       " '__reduce__',\n",
       " '__reduce_ex__',\n",
       " '__repr__',\n",
       " '__setattr__',\n",
       " '__sizeof__',\n",
       " '__str__',\n",
       " '__subclasshook__',\n",
       " '__weakref__',\n",
       " '_call_func',\n",
       " 'close',\n",
       " 'get_num_devices',\n",
       " 'open',\n",
       " 'open_device',\n",
       " 'read',\n",
       " 'val',\n",
       " 'write']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Grove ADC responds to address 0x50 and to read from it we need to write the register we want (0 for the result) and then read the two bytes back."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "831"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "buf = bytearray(2)\n",
    "buf[0] = 0\n",
    "device.write(0x50, buf, 1)\n",
    "device.read(0x50, buf, 2)\n",
    "\n",
    "((buf[0] & 0x0F) << 8) | buf[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This same approach can be used for all of the other libraries either included with PYNQ or from other sources."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
